<template>
  <div v-if="config.filter != null" class="p-4 bg-slate-50 border border-solid border-slate-200 mb-2">
    <a-form :model="formState"
            layout="inline"
            style="margin-top: -12px;"
            @finish="handleSearch">

      <a-form-item v-for="control in controls"
                   :key="control.key"
                   :label="control.label"
                   :name="control.key"
                   style="margin-top: 12px;">
        <!-- 文本 -->
        <template v-if="control.type === 'text'">
          <a-input v-model:value.trim="formState[control.key]"
                   :placeholder="control.placeholder || `全部`"
                   allow-clear/>
        </template>

        <!-- 日期范围 -->
        <template v-else-if="control.type === 'dateRange'">
          <a-range-picker v-model:value="formState[control.key]"
                          :picker="control.config?.mode ?? 'date'"
                          :placeholder="['开始时间', '结束时间']"/>
        </template>

        <!-- 日期 -->
        <template v-else-if="control.type === 'date'">
          <a-date-picker v-model:value="formState[control.key]" placeholder="全部"/>
        </template>

        <!-- 数值 -->
        <template v-else-if="control.type === 'numeric'">
          <a-input-number v-model:value="formState[control.key]" placeholder="全部"/>
        </template>

        <!-- 下拉选择 -->
        <template v-else-if="control.type === 'select'">
          <a-select v-model:value="formState[control.key]"
                    :style="{ width: control.config.width ?? 150 + 'px' }"
                    allow-clear
                    placeholder="全部">
            <a-select-option v-for="option in control.config.options" :key="option.value">
              {{ option.text }}
            </a-select-option>
          </a-select>
        </template>

        <!-- 下拉查询 -->
        <template v-else-if="control.type === 'search'">
          <search-control v-model:value="formState[control.key]"
                          :control="control"
                          :style="{ width: control.config.width ?? 200 + 'px' }"
                          placeholder="全部"/>
        </template>
      </a-form-item>

      <a-form-item style="margin-top: 12px;">
        <a-space>
          <a-button html-type="submit" type="primary">
            <search-outlined/>
            查询
          </a-button>
          <a-button v-if="config.export != null && allowed(config.export.permission)"
                    html-type="button"
                    @click="handleExport">
            <export-outlined/>
            导出
          </a-button>
        </a-space>
      </a-form-item>
    </a-form>
  </div>
</template>

<script setup>
import {ExportOutlined, SearchOutlined} from "@ant-design/icons-vue";
import {serializeParams} from "../composables/api.js";
import {allowed} from "../profile.js";

const {config, extraParams} = defineProps(['config', 'extraParams']);
const emit = defineEmits(['submit']);

const {data: initData, isLoading: initLoading, execute: loadInitData} = useApi({
  url: config.filter?.initUrl,
  immediate: false
});
if (config.filter?.initUrl != null) {
  loadInitData();
}

const controls = computed(() => {
  const initDataValue = initData.value;
  return (config.filter?.controls ?? []).map(control => {
    const config = {...control.config};
    if (control.type === 'select') {
      const options = config.options;
      if (typeof options === 'string') {
        config.options = initDataValue?.[options]?.map(option => {
          return {
            text: typeof config.textKey === 'function'
              ? config.textKey(option)
              : option[config.textKey],
            value: option[config.valueKey]
          };
        }) ?? [];
      }
    } else if (control.type === 'tree') {
      const options = config.options;
      if (typeof options === 'function') {
        config.options = options();
      }
    } else if (control.type === 'search') {
      const initOptions = config.initOptions;
      if (typeof initOptions === 'string') {
        const options = initDataValue?.[initOptions];
        config.initOptions = options == null
          ? []
          : Array.isArray(options) ? options : [options];
      }
    }
    config.placeholder = ['date', 'datetime', 'select', 'search', 'cascader'].includes(control.type)
      ? '选择' + control.label
      : '输入' + control.label;
    return {
      ...control,
      config
    };
  });
});

const formState = reactive(controls.value.reduce((prev, control) => {
  prev[control.key] = control.config?.initialValue;
  return prev;
}, {}));

const getParams = () => {
  return {
    ...extraParams,
    ...controls.value.reduce((prev, control) => {
      const value = formState[control.key];
      if (control.type === 'dateRange') {
        if (value != null) {
          prev[control.key + 'OnOrAfter'] = value[0].format('YYYY-MM-DD') + ' 00:00:00';
          prev[control.key + 'OnOrBefore'] = value[1].format('YYYY-MM-DD') + ' 23:59:59';
        }
      } else if (control.type === 'text') {
        if (value != null && value?.length > 0) {
          prev[control.key] = value;
        }
      } else {
        if (value != null) {
          prev[control.key] = value;
        }
      }
      return prev;
    }, {})
  };
}

const handleSearch = async () => {
  emit('submit', getParams());
};

const handleExport = async () => {
  window.location.href = `/api/${config.export.url}?${serializeParams(getParams())}`;
}

defineExpose({getParams});
</script>

<style lang="scss" scoped>

</style>
